﻿using System;
using System.Linq;
using ZbUtil.IO.Ports;

namespace ZbUtil.Sample
{
    class Program
    {
        private static readonly string PortName = "COM5";
        private static readonly int BaudRate = 9600;

        static void Main()
        {
            var serialPortStreamHelper = new SerialPortStreamHelper()
            {
                DtrEnable = true,
                RtsEnable = true
            };
            serialPortStreamHelper.DataReceived += OnDataReceived;

            try
            {
                if (!serialPortStreamHelper.Open(PortName, BaudRate))
                {
                    Console.WriteLine($@"{serialPortStreamHelper.LastErrorMessage}");
                    Console.WriteLine("Press any key to exit...");
                    Console.ReadKey();
                    return;
                }

                Console.WriteLine();
                Console.WriteLine("Input data sample: 0x01 0x05 0x03 0xFD");
                Console.WriteLine("Please input data('q' to stop): ");
                while (true)
                {
                    var input = Console.ReadLine()?.Trim();
                    if (input == null || input.Length == 1 && input.ToUpper()[0] == 'Q')
                    {
                        break;
                    }

                    try
                    {
                        var bytes = GetBytes(input);
                        if (bytes != null)
                        {
                            serialPortStreamHelper.Write(bytes);
                        }
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e);
                    }

                    Console.WriteLine("Please input data('q' to stop): ");
                }

                //关闭服务
                serialPortStreamHelper.Close();
            }
            catch (Exception e)
            {
                Console.WriteLine($"Exception happened: {e.Message}");
                Console.WriteLine("Press any key to exit...");
                Console.ReadKey();
                return;
            }

            serialPortStreamHelper.Dispose();

            Console.WriteLine();
            Console.WriteLine("The server was stopped!");
            Console.WriteLine("Press any key to exit...");
            Console.ReadKey();
            Console.WriteLine();
        }

        private static void OnDataReceived(string portName, byte[] data)
        {
            var text = string.Join(" ", data.Select(t => t.ToString("X2")));
            Console.WriteLine($@"Receive data from {portName}: {text}.");

            for (var i = 0; i < data.Length; i++)
            {
                int packetDataLen;

                //校验数据测试，需要实现自己的业务逻辑，相当于解包
                if (CheckData(data, out packetDataLen, i))
                {
                    //TODO：打印数据(buffer, offset, packetDataLen)
                    //PrintPacketInfo(data, i, packetDataLen)

                    //进行下一个包的检测
                    i += packetDataLen - 1;
                }
            }
        }

        private static bool CheckData(byte[] buffer, out int packetDataLen, int offset = 0)
        {
            packetDataLen = 0;

            //header type dataLen Cks1 Cks2
            if (buffer.Length - offset < 5)
            {
                return false;
            }

            //Check header
            if (buffer[offset] != 0x01)
            {
                return false;
            }

            //Check type
            if (buffer[offset + 1] != 0x03 && buffer[offset + 1] != 0x04)
            {
                return false;
            }

            var dataLen = (int)buffer[offset + 2];
            packetDataLen = dataLen + 5;
            if (buffer.Length < packetDataLen)
            {
                return false;
            }

            //TODO: 校验数据
            return true;
        }

        private static byte[] GetBytes(string text)
        {
            var dataArray = text?.Split(' ');
            if (dataArray == null || dataArray.Length == 0)
            {
                return null;
            }

            var bytes = new byte[dataArray.Length];
            for (var i = 0; i < dataArray.Length; i++)
            {
                bytes[i] = Convert.ToByte(dataArray[i], 16);
            }

            return bytes;
        }
    }
}
